import os
import random
import sys
import time
import urllib.request
from pathlib import Path

import requests as req
from loguru import logger

from mdtool.error_handler import (
    ErrorLevel,
    FileSystemError,
    ImageError,
    error_handler,
)

DOWNLOADED_FROM_WEB = "downloaded"

# 图片格式的魔数
IMAGE_MAGIC_NUMBERS = {
    b"\xff\xd8\xff": "JPEG",
    b"\x89PNG\r\n\x1a\n": "PNG",
    b"GIF87a": "GIF",
    b"GIF89a": "GIF",
    b"BM": "BMP",
    b"\x00\x00\x01\x00": "ICO",
}


def is_valid_dir(dir_path):
    return (
        dir_path
        and Path(dir_path).exists()
        and Path(dir_path).is_dir()
        and os.access(dir_path, os.R_OK)
    )


def is_valid_file(file_path):
    return file_path and Path(file_path).exists() and Path(file_path).is_file()


def is_image_format(header):
    for magic in IMAGE_MAGIC_NUMBERS:
        if header.startswith(magic):
            logger.debug(f"image has header {header},which is a valid image format.")
            return True
    logger.warning(f"image has header {header}, which is not a valid image format.")
    return False


def http_url_get(url: str):
    headers = {  # "Content-type": "text/plain; charset=utf-8",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
        "cookie": "appmsglist_action_3091036559=card; ua_id=1FhELt8zASmlerk1AAAAAEhaLHGINxNalpZNh_V1rt8=; mdtool.in=42445030160391; mm_lang=zh_CN; pac_uid=0_t7c93jQ39t6ze; suid=user_0_t7c93jQ39t6ze; _qimei_uuid42=1931508222c10094c78eba5544cce2a482e3a12908; _qimei_fingerprint=b0c3f3782766c65eec961dae2741a241; _qimei_h38=d53f7e69c78eba5544cce2a40300000d819315; _qimei_q36=; _clck=3091036559|1|fwg|0; uuid=77fb7c4ce81232a86cf11b3816f8a5a4; rand_info=CAESIPw6ggH9lepnnPHyDjDJjwbMFliX3UHYtkfHOARkjMjp; slave_bizuin=3091036559; data_bizuin=3091036559; bizuin=3091036559; data_ticket=USzWE7t3ZzNMTmRalShK/oRGRc7RR7gP+CN4bOeE2bJJdhAr2xHP0h2T547FHlw0; slave_sid=QnpfaUJ0c0w3YTEzVlVzeEY4NTg4X1dncDdDejgxdzZRVUpkYlU3ckxfTzV6MUJLZnBaWkNZMVlFWHdJV3Z6dHdCbndTTFpkT0J1R2FBdTl1Y0NsSVNpVThPRVNNWTlqS09nVzVydHplb2E3Yk4zdmltQUpUakd4SVVrNDBMN0hMbGJSRnBsTjBJY0Y3eThB; slave_user=gh_a37c550bbfbd; xid=54b1cb6808aabb2dde0af15f652f677c; rewardsn=; mdtool.okenkey=777; _clsk=1sf5sav|1748994485499|17|1|mp.weixin.qq.com/weheat-agent/payload/record",
    }
    round = 3
    try:
        # 随机暂停几秒，避免过快的请求导致过快的被查到
        while round > 0:
            round -= 1
            time.sleep(random.randint(1, 10))
            resp = req.get(url, headers=headers)
            resp.raise_for_status()
            # resp.encoding = 'utf-8'
            if resp.json()["base_resp"]["ret"] == 200013:
                logger.debug("frequencey control")
                time.sleep(3600)
                continue
            return resp
        return resp
    except req.exceptions.RequestException as e:
        logger.warning(f"请求发生错误: {e}")
        return None


def is_valid_image(file_path):
    if file_path.startswith("http"):
        return check_image_url(file_path)
    if not os.path.isfile(file_path):
        return False
    if not os.access(file_path, os.R_OK):
        return False
    with open(file_path, "rb") as f:
        header = f.read(8)
        return is_image_format(header)


def check_image_url(img_url: str) -> bool:
    max_retries = 3
    for attempt in range(max_retries):
        try:
            # 添加随机延迟0.5-3秒，避免过快访问
            time.sleep(random.uniform(0.5, 3))
            with urllib.request.urlopen(img_url) as response:
                # 1. 检查 Content-Type
                content_type = response.headers.get("Content-Type", "")
                if not content_type.startswith("image/"):
                    logger.info(
                        f"image {img_url} has content-type {content_type}, which is not a valid image url."
                    )
                    return False
                # 2. 读取内容并验证
                content = response.read(8)
                return is_image_format(content)
        except Exception as e:
            if attempt < max_retries - 1:
                logger.warning(f"验证图片URL失败，第{attempt + 1}次尝试: {img_url}, 错误: {str(e)}")
                time.sleep(5)  # 重试前等待5秒
                continue
            else:
                logger.error(f"验证图片URL失败，已重试{max_retries}次: {img_url}, 错误: {str(e)}")
                print(f"错误: 无法验证图片URL {img_url}，已重试{max_retries}次。程序退出。")
                sys.exit(1)
    return False


def download_image_to_dir(img_url: str, target_dir: str) -> str:
    max_retries = 3

    # Create target directory if it doesn't exist
    try:
        os.makedirs(target_dir, exist_ok=True)
    except Exception as e:
        logger.warning(f"Failed to create image download directory: {str(e)}")
        raise FileSystemError(
            f"Failed to create image download directory: {str(e)}"
        ) from e

    for attempt in range(max_retries):
        try:
            # 添加随机延迟0.5-3秒，避免过快访问
            time.sleep(random.uniform(0.5, 3))
            resource = urllib.request.urlopen(img_url)

            # Get file extension from URL or default to .png
            file_ext = os.path.splitext(img_url.split("/")[-1])[1]
            if not file_ext:
                file_ext = ".png"

            # Generate a unique filename using timestamp
            timestamp = int(time.time())
            name = f"image_{timestamp}{file_ext}"
            f_name = os.path.join(target_dir, name)

            try:
                with open(f_name, "wb") as f:
                    f.write(resource.read())
                return f_name
            except Exception as e:
                logger.warning(f"Failed to save image to {f_name}: {str(e)}")
                raise FileSystemError(f"Failed to save image to {f_name}: {str(e)}") from e

        except Exception as e:
            if attempt < max_retries - 1:
                logger.warning(f"下载图片失败，第{attempt + 1}次尝试: {img_url}, 错误: {str(e)}")
                time.sleep(5)  # 重试前等待5秒
                continue
            else:
                logger.error(f"下载图片失败，已重试{max_retries}次: {img_url}, 错误: {str(e)}")
                print(f"错误: 无法下载图片 {img_url}，已重试{max_retries}次。程序退出。")
                sys.exit(1)

    # 这里不应该到达，但为了安全起见
    raise ImageError(f"Failed to download image from {img_url} after {max_retries} attempts")


def md5(content: bytes):
    import hashlib

    m = hashlib.md5()
    m.update(content)
    return m.hexdigest()
